<?php

namespace common\helpers;

use common\services\AwsService;
use Yii;
use yii\web\UploadedFile;

/**
 * 文件通用上传类
 * Class Upload
 * @package common\helpers
 * @desc
 *    $upload = new Upload('file');
 *    $upload->setMaxSize( 5 * 1024);
 *    $upload->setFileType( ['jpg','jpeg']);
 *    $a = $upload->getImageSize();
 */
class Upload
{
    //上传驱动
    private $driver = 'oss';

    //文件key
    public $formFileKey = 'file';
    //最大大小
    public $fileMaxSize = 0;
    //文件类型
    public $fileType = [];

    public $files = null;


    public function __construct(string $formFileKey)
    {
        $this->formFileKey = $formFileKey;
        $this->files = UploadedFile::getInstancesByName($this->formFileKey);
    }


    /**
     * 文件大小限制 字节
     * @param $size
     */
    public function setMaxSize(int $size)
    {
        $this->fileMaxSize = $size;
    }

    /**
     * 设置文件
     * @param string $filePath
     * @return UploadedFile
     */
    public function setFiles(string $filePath)
    {
        if (!is_file($filePath)) {
            throw new FileUploadException("文件不正确");
        }
        $fileInfo = pathinfo($filePath);
        $file = new UploadedFile();
        $file->name = $fileInfo['basename'] ?? '';
        $file->tempName = $fileInfo['basename'] ?? '';
        $file->type = $fileInfo['extension'];
        $file->size = filesize($filePath);
        $this->files = [$file];
    }

    /**
     * 文件类型
     * @param $type | ['jpg','jpeg']
     */
    public function setFileType(array $type)
    {
        $this->fileType = $type;
    }

    /**
     * 设置驱动类型
     * @param string $name
     */
    public function setDriver(string $name)
    {
        $this->driver = $name;
    }


    /**
     * 获取图片信息
     * @return array
     */
    public function getImageSize()
    {
        $images = [];
        foreach ($this->files as $index => $file) {
            $pathInfo = pathinfo($file->name);
            $extension = $pathInfo['extension'];
            list($width, $height, $type, $attr) = getimagesize($file->tempName);
            $images[$index] = [
                'name' => $file->name,
                'tempName' => $file->tempName,
                'type' => $file->type,
                'extension' => $extension,
                'size' => $file->size,
                'width' => $width,
                'height' => $height,
            ];
        }
        return $images;
    }


    /**
     * 上传验证
     * @return bool
     * @throws FileUploadException
     */
    private function validate()
    {

        if (!empty($this->files)) {

            if ($this->fileMaxSize || $this->fileType) {
                foreach ($this->files as $index => $file) {
                    $extension = $this->getExtension($file);
                    //验证大小
                    if ($this->fileMaxSize && $file->size > $this->fileMaxSize) {
                        throw new FileUploadException('上传文件超过指定的大小:' . $this->fileMaxSize);
                    }
                    //验证类型
                    if (!in_array($extension, $this->fileType)) {
                        throw new FileUploadException('文件类型受限制:' . $file->type);
                    }
                }
            }
        } else {
            throw new FileUploadException('上传文件不能为空');
        }

        return true;
    }

    /**
     * @param UploadedFile $file
     * @return string
     */
    private function getExtension(UploadedFile $file)
    {
        if ($file->name == 'blob') {
            $extension = explode('/', $file->type)[1] ?? 'null';
        } else {
            $pathInfo = pathinfo($file->name);
            $extension = $pathInfo['extension'];
        }
        return $extension;

    }

    /**
     * 上传文件保存
     * @param string $pathDir 挂载目录
     * @param string $bucket 三方存储工具bucket名字 本地上传无需此参数
     * @return array|mixed
     * @throws FileUploadException
     * @throws \Throwable
     */
    public function save($pathDir, $bucket = '')
    {
        //验证
        $this->validate();
        $fileInfo = [];
        foreach ($this->files as $index => $file) {

            $extension = $this->getExtension($file);
            list ($a, $b) = explode(" ", microtime());
            $nameName = $b . str_replace('.', '', $a) . uniqid() . mt_rand(10000, 99999) . '.' . $extension;

            try {

                $fileFullName = rtrim($pathDir, '/') . '/' . $nameName;
                switch ($this->driver) {
                    case 'oss':
                        $fileFullName = ltrim($fileFullName, '/');
                        OssHelper::uploadFile($fileFullName, $file->tempName, $bucket);
                        $fileFullName = OssHelper::getPublicUrl($fileFullName);
                        break;
                    case 'aws':
                        $aws = new AwsService();
                        $awsResult = $aws->uploadFileToAws($file->tempName, $fileFullName);
                        if ($awsResult == false) {
                            throw new FileUploadException('上传失败');
                        }
                        $fileFullName = $awsResult['full_url'];
                        break;
                    default:

                        //保存到frontend module下
                        $basePath = Yii::getAlias('@frontend') . '/web';

                        $directory = '/uploads/' . $pathDir . '/' . date("Y-m-d");

                        $localPathDir = $basePath . $directory;

                        //本地上传
                        if (!is_dir($localPathDir)) {
                            @mkdir($localPathDir, 0777, true);
                            @chmod($localPathDir, 0777);
                        }
                        if (!$file->saveAs($localPathDir . '/' . $nameName)) {
                            throw new FileUploadException($file->error);
                        }

                        //文件host地址
                        $fileFullName = Yii::$app->params['hostUrl'] . $directory . '/' . $nameName;

                }
                $fileInfo[$index] = [
                    'name' => $file->name,
                    'tempName' => $file->tempName,
                    'type' => $file->type,
                    'extension' => $extension,
                    'size' => $file->size,
                    'fullName' => $fileFullName, // 文件上传存储目录
                ];

            } catch (\Throwable $throwable) {
                throw  $throwable;
            }
        }
        return $fileInfo;

    }

}

class FileUploadException extends \Exception
{
}

